package com.example.pcl.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.pcl.constant.JwtClaimsConstant;
import com.example.pcl.exception.ObjectException;
import com.example.pcl.mapper.AppointmentsMapper;
import com.example.pcl.mapper.CounselorsMapper;
import com.example.pcl.mapper.StudentFeedbackMapper;
import com.example.pcl.mapper.UsersMapper;
import com.example.pcl.pojo.dto.CounselorQueryDto;
import com.example.pcl.pojo.entity.*;
import com.example.pcl.pojo.vo.ConsultationStatsVO;
import com.example.pcl.pojo.vo.ConsultationStatsVO2;
import com.example.pcl.pojo.vo.RatingVO;
import com.example.pcl.service.IAppointmentsService;
import com.example.pcl.service.IConsultationRecordsService;
import com.example.pcl.service.ICounselorsService;
import com.example.pcl.service.IUsersService;
import com.example.pcl.utils.Util;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 心理咨询师表，存储心理咨询师个人信息 服务实现类
 * </p>
 *
 * @author xx
 * @since 2024-12-17
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CounselorsServiceImpl extends ServiceImpl<CounselorsMapper, Counselors> implements ICounselorsService {

    private final IAppointmentsService appointmentsService;
    private final IConsultationRecordsService recordsService;
    private final UsersMapper usersMapper;
    private final AppointmentsMapper appointmentMapper;
    private final StudentFeedbackMapper feedbackMapper;

    /**
     * 添加心理咨询师
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCounselor(@NotNull Counselors counselor) {
        // 检查工号是否重复（用户名是否唯一）
        if (usersMapper.selectCount(new LambdaQueryWrapper<Users>().eq(Users::getUsername, counselor.getWorkNumber())) > 0) {
            throw new ObjectException("工号已存在，请检查！");
        }

        // 插入用户信息
        Users user = Users.builder().role(Users.COUNSELOR).accountStatus(Users.NORMAL).username(counselor.getWorkNumber()).password(Util.encryptPassword(JwtClaimsConstant.INITIAL_PASSWORD)).build();
        if (usersMapper.insert(user) <= 0) {
            throw new ObjectException("添加用户信息失败，请重试！");
        }

        // 检查心理咨询师是否重复
        boolean exists = lambdaQuery().eq(Counselors::getName, counselor.getName()).eq(Counselors::getQualification, counselor.getQualification()).exists();
        if (exists) {
            throw new ObjectException("心理咨询师已存在！");
        }

        // 插入心理咨询师记录
        if (!save(counselor.setUserId(user.getUserId()))) {
            throw new ObjectException("添加心理咨询师失败，请重试！");
        }
    }

    /**
     * 删除心理咨询师
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCounselor(Integer id) {
        // 检查是否存在未完成的预约记录
        boolean hasPendingAppointments = appointmentsService.lambdaQuery().eq(Appointments::getCounselorId, id).in(Appointments::getStatus, List.of(Appointments.TO_BE_CONFIRMED, Appointments.CONFIRMED)).exists();
        if (hasPendingAppointments) {
            throw new ObjectException("该心理咨询师存在未完成的预约记录，无法删除！");
        }

        // 查询关联的预约 ID
        List<Integer> ids = appointmentsService.listObjs(new LambdaQueryWrapper<Appointments>().select(Appointments::getAppointmentId).eq(Appointments::getCounselorId, id), obj -> (Integer) obj // 转换为 Integer 类型
        );

        // 删除关联访谈记录
        if (ids != null && !ids.isEmpty()) {
            recordsService.remove(new LambdaQueryWrapper<ConsultationRecords>().in(ConsultationRecords::getAppointmentId, ids));
        }

        // 删除心理咨询师记录
        if (!removeById(id)) {
            throw new ObjectException("删除心理咨询师失败！");
        }

        // 删除用户表记录
        int userDeleted = usersMapper.delete(new LambdaUpdateWrapper<Users>().eq(Users::getUserId, id).eq(Users::getRole, Users.COUNSELOR));
        if (userDeleted == 0) {
            throw new ObjectException("删除心理咨询师用户信息失败！");
        }
    }

    /**
     * 更新心理咨询师信息
     */
    @Override
    public void updateCounselor(Counselors counselor) {
        if (!updateById(counselor)) {
            throw new ObjectException("更新心理咨询师信息失败！");
        }
    }

    /**
     * 查询所有心理咨询师（支持条件查询）
     */
    @Override
    public List<?> listAll(@NotNull CounselorQueryDto queryDto) {
        String availableSlots = queryDto.getAvailableSlots();
        String name = queryDto.getName();
        Integer isOnDuty = queryDto.getIsOnDuty();
        String specialtyArea = queryDto.getSpecialtyArea();
        return list(new LambdaQueryWrapper<Counselors>().like(StringUtils.isNotEmpty(name), Counselors::getName, name).eq(StringUtils.isNotEmpty(availableSlots), Counselors::getAvailableSlots, availableSlots).eq(ObjectUtil.isNotNull(isOnDuty), Counselors::getIsOnDuty, isOnDuty).like(StringUtils.isNotEmpty(specialtyArea), Counselors::getSpecialtyArea, specialtyArea));
    }

    /**
     * 更新心理咨询师值班状态
     */
    @Override
    public void updateDutyStatus(Integer id, Integer isOnDuty) {
        Counselors counselor = getById(id);
        if (counselor == null) {
            throw new ObjectException("心理咨询师不存在！");
        }
        counselor.setIsOnDuty(isOnDuty);
        if (!updateById(counselor)) {
            throw new ObjectException("更新心理咨询师值班状态失败！");
        }
    }

    // 获取心理咨询师的预约统计数据
    @Override
    public ConsultationStatsVO getConsultationStatsByCounselor(Integer counselorId) {


        Long pendingAppointments = appointmentMapper.selectCount(
                new LambdaQueryWrapper<Appointments>()
                        .eq(Appointments::getCounselorId, counselorId)
                        .eq(Appointments::getStatus, Appointments.TO_BE_CONFIRMED));

        Long completedAppointments = appointmentMapper.selectCount(
                new LambdaQueryWrapper<Appointments>()
                        .eq(Appointments::getCounselorId, counselorId)
                        .eq(Appointments::getStatus, Appointments.COMPLETED));

        Map<String, Object> result = feedbackMapper.getReviewStatsByCounselorId(counselorId);

        Object totalReviewsObj = result.get("totalReviews");
        Object goodReviewsObj = result.get("goodReviews");

        double rating = 0.0;

        if (totalReviewsObj instanceof Long totalReviews && goodReviewsObj instanceof BigDecimal goodReviews) {

            if (totalReviews > 0) {
                rating = goodReviews.divide(BigDecimal.valueOf(totalReviews), 2, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100))
                        .doubleValue();
            }
        }

        return new ConsultationStatsVO(pendingAppointments, completedAppointments, rating);
    }


    // 获取心理咨询师的咨询量分布
    @Override
    public List<ConsultationStatsVO2> getConsultationVolumeByCounselor(Integer counselorId) {
        // 获取今天日期的前后某个时间段的预约量
        LocalDate startDate = LocalDate.now().plusDays(7);
        LocalDate endDate = LocalDate.now();

        // 查询数据
        LambdaQueryWrapper<Appointments> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Appointments::getCounselorId, counselorId);
        queryWrapper.ge(Appointments::getAppointmentDate, endDate);
        queryWrapper.le(Appointments::getAppointmentDate, startDate);
        queryWrapper.orderByAsc(Appointments::getAppointmentDate);

        List<Appointments> appointments = appointmentMapper.selectList(queryWrapper);

        return appointments.stream()
                .collect(Collectors.groupingBy(Appointments::getAppointmentDate,
                        Collectors.groupingBy(Appointments::getAppointmentMethod, Collectors.counting())))
                .entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .map(entry -> new ConsultationStatsVO2(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }


}

